﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="LocationActioner.cs" company="DissingNelleman">
//   
// All rights reserved. </copyright>
// <summary>
//   The location actioner.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace ServiceLibrary.Actioners.Locations
{
    using System;
    using System.Collections.Generic;
    using System.Linq;

    using NHibernate;

    using ServiceLibrary.Models.Base;
    using ServiceLibrary.Models.Domain;
    using ServiceLibrary.Services.Commands;
    using ServiceLibrary.Services.Queries;
    using ServiceLibrary.Services.Results;

    /// <summary>
    /// The location actioner.
    /// </summary>
    public class LocationActioner : ActionerBase
    {
        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="LocationActioner"/> class.
        /// </summary>
        /// <param name="session">
        /// The session.
        /// </param>
        /// <param name="activeUser">
        /// The active user.
        /// </param>
        public LocationActioner(ISession session, User activeUser)
            : base(session, activeUser)
        {
        }

        #endregion

        #region Public Methods and Operators

        /// <summary>
        /// The create default locations related objects.
        /// </summary>
        public void CreateDefaultLocationsRelatedObjects()
        {
            Guid tmpID;

            var countryActioner = new CountryActioner(this.Session, this.ActiveUser);
            var regionActioner = new RegionActioner(this.Session, this.ActiveUser);

            IList<Country> countries = this.Session.QueryOver<Country>().List();

            var sydID = Guid.Empty;

            bool exists = (from c in countries where c.Name.Equals("Danmark") select c).Any();
            if (!exists)
            {
                tmpID = countryActioner.CreateCountry("Danmark");
                Country denmark = countryActioner.GetCountry(tmpID);
                var danishRegions = new List<string> { "Syd", "Midt", "Nord", "Sjælland", "Hovedstaden" };
                foreach (string region in danishRegions)
                {
                    Guid regID = regionActioner.CreateRegion(region, denmark, string.Empty);
                    if (region.Equals("Syd", StringComparison.CurrentCultureIgnoreCase))
                    {
                        sydID = regID;
                    }
                }
            }

            exists = (from c in countries where c.Name.Equals("Tyskland") select c).Any();
            if (!exists)
            {
                tmpID = countryActioner.CreateCountry("Tyskland");
                Country germany = countryActioner.GetCountry(tmpID);
                var germanRegions = new List<string> { "Slesvig", "Holstein", "Lübech", "Hamburg" };
                foreach (string region in germanRegions)
                {
                    regionActioner.CreateRegion(region, germany, string.Empty);
                }
            }

            var otherCountries = new List<string>
                                     {
                                         "England", 
                                         "USA", 
                                         "Kina", 
                                         "Andre EU", 
                                         "Andre Nord Amerika", 
                                         "Andre Brik", 
                                         "Andre"
                                     };
            foreach (string country in otherCountries)
            {
                exists = (from c in countries where c.Name.Equals(country) select c).Any();
                if (!exists)
                {
                    tmpID = countryActioner.CreateCountry(country);
                    Country other = countryActioner.GetCountry(tmpID);
                    regionActioner.CreateRegion("Landsdækkende", other, string.Empty);
                }
            }

            if (!sydID.Equals(Guid.Empty))
            {
                Region syd = regionActioner.GetRegion(sydID);
                var addr = new Address
                               {
                                   ID = Guid.NewGuid(), 
                                   Att = string.Empty, 
                                   City = "Odense", 
                                   StreetName = "Forskerparken", 
                                   Zip = "5230", 
                                   StreetNr = "10H"
                               };
                var aa = new AddressActioner(this.Session, this.ActiveUser);
                aa.CreateAddress(addr);

                var loc = new Location
                              {
                                  ID = Guid.NewGuid(), 
                                  Name = "WT Lab", 
                                  Within150Km = true, 
                                  Region = syd, 
                                  Address = addr
                              };

                var lAction = new LocationActioner(this.Session, this.ActiveUser);
                lAction.CreateLocation(loc);
            }
        }

        /// <summary>
        /// The create location.
        /// </summary>
        /// <param name="location">
        /// The location.
        /// </param>
        public void CreateLocation(Location location)
        {
            location.CreatedDateTime = DateTime.Now;
            this.Session.Save(location);

            this.Log.CreateLogEntry(
                location.ID, 
                string.Format("Lokation '{0}, {1}', blev oprettet.", location.Name, location.Region.Name), 
                Enums.LogEntryType.Location);
        }

        /// <summary>
        /// The create location.
        /// </summary>
        /// <param name="command">
        /// The command.
        /// </param>
        public void CreateLocation(CreateLocationCommand command)
        {
            if (command.NewLocation != null)
            {
                var location = new Location();
                location.ID = command.NewLocation.ID;
                location.Within150Km = command.NewLocation.Within150Km;
                location.Name = command.NewLocation.Name;

                if (command.NewLocation.Address != null)
                {
                    var aa = new AddressActioner(this.Session, this.ActiveUser);
                    Address addr = aa.GetAddress(command.NewLocation.Address.ID);
                    if (addr == null)
                    {
                        addr = new Address
                                   {
                                       ID = command.NewLocation.Address.ID, 
                                       StreetName = command.NewLocation.Address.StreetName, 
                                       Att = command.NewLocation.Address.Att, 
                                       City = command.NewLocation.Address.City, 
                                       StreetNr = command.NewLocation.Address.StreetNr, 
                                       Zip = command.NewLocation.Address.Zip
                                   };
                        aa.CreateAddress(addr);
                    }

                    location.Address = addr;
                }

                if (command.NewLocation.Region != null)
                {
                    var ra = new RegionActioner(this.Session, this.ActiveUser);
                    Region region = ra.GetRegion(command.NewLocation.Region.ID);
                    if (region != null)
                    {
                        location.Region = region;
                    }
                }

                CreateLocation(location);
            }
        }

        /// <summary>
        /// The execute search query.
        /// </summary>
        /// <param name="query">
        /// The query.
        /// </param>
        /// <returns>
        /// The <see cref="LocationsResult"/>.
        /// </returns>
        public LocationsResult ExecuteSearchQuery(LocationsQuery query)
        {
            SearchSettings settings = query.Settings;

            var result = new LocationsResult();

            IQueryOver<Location, Location> search = this.Session.QueryOver<Location>();
            this.ApplyDefaultCriterias(settings, search);

            int rowCount = search.RowCount();
            var locations = this.ApplySkipAndTake(settings, search.OrderBy(x => x.Name).Asc);

            result.TotalRowCount = rowCount;

            foreach (Location location in locations)
            {
                Services.Dto.Location dto = Services.Dto.Location.Convert(location);
                if (dto != null)
                {
                    result.List.Add(dto);
                }
            }

            return result;
        }

        /// <summary>
        /// The get location.
        /// </summary>
        /// <param name="id">
        /// The id.
        /// </param>
        /// <returns>
        /// The <see cref="Location"/>.
        /// </returns>
        public Location GetLocation(Guid id)
        {
            var where = this.Session.Get<Location>(id);

            return where;
        }

        #endregion

        #region Methods

        /// <summary>
        /// The update location.
        /// </summary>
        /// <param name="cmd">
        /// The cmd.
        /// </param>
        internal void UpdateLocation(UpdateLocationCommand cmd)
        {
            if (cmd.Dto != null)
            {
                var location = this.Session.Get<Location>(cmd.Dto.ID);
                if (location != null)
                {
                    location.Within150Km = cmd.Dto.Within150Km;
                    location.Name = cmd.Dto.Name;

                    if (cmd.Dto.Address != null)
                    {
                        var aa = new AddressActioner(this.Session, this.ActiveUser);
                        Address addr = aa.GetAddress(cmd.Dto.Address.ID);
                        if (addr == null)
                        {
                            addr = new Address
                                       {
                                           ID = cmd.Dto.Address.ID, 
                                           StreetName = cmd.Dto.Address.StreetName, 
                                           Att = cmd.Dto.Address.Att, 
                                           City = cmd.Dto.Address.City, 
                                           StreetNr = cmd.Dto.Address.StreetNr, 
                                           Zip = cmd.Dto.Address.Zip
                                       };
                            aa.CreateAddress(addr);
                        }
                        else
                        {
                            addr.StreetName = cmd.Dto.Address.StreetName;
                            addr.Att = cmd.Dto.Address.Att;
                            addr.City = cmd.Dto.Address.City;
                            addr.StreetNr = cmd.Dto.Address.StreetNr;
                            addr.Zip = cmd.Dto.Address.Zip;
                            this.Session.Update(addr);
                        }

                        location.Address = addr;
                    }

                    if (cmd.Dto.Region != null)
                    {
                        var ra = new RegionActioner(this.Session, this.ActiveUser);
                        Region region = ra.GetRegion(cmd.Dto.Region.ID);
                        if (region != null && region.ID != location.Region.ID)
                        {
                            location.Region = region;
                        }
                    }

                    this.Session.Update(location);
                }
            }
        }

        #endregion
    }
}